package cn.zl.ymcc.gen;

import cn.zl.ymcc.gen.config.CodeGeneratorConfig;
import com.baomidou.mybatisplus.generator.FastAutoGenerator;
import com.baomidou.mybatisplus.generator.config.OutputFile;
import com.baomidou.mybatisplus.generator.config.rules.DbColumnType;
import com.baomidou.mybatisplus.generator.engine.VelocityTemplateEngine;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;

import java.sql.Types;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

@Component
public class CodeGenerator {
    @Autowired
    private CodeGeneratorConfig codeGeneratorConfig;
    
    @Value("${spring.datasource.url}")
    private String url;
    
    @Value("${spring.datasource.username}")
    private String username;
    
    @Value("${spring.datasource.password}")
    private String password;
    
    @Value("${code.generator.base-package}")
    private String basePackage;
    
    @Value("${code.generator.author}")
    private String author;
    
    @Value("${code.generator.output-dir}")
    private String outputDir;
    
    @Value("${code.generator.table-prefix:t_}")
    private String tablePrefix;
    
    /**
     * 生成代码
     * @param tableNames 表名数组
     */
    public void generate(String... tableNames) {
        Map<OutputFile, String> pathInfo = new HashMap<>();

        // 设置不同文件的输出目录
        pathInfo.put(OutputFile.entity, codeGeneratorConfig.getEntityOutputDir());
        pathInfo.put(OutputFile.mapper, codeGeneratorConfig.getMapperOutputDir());
        pathInfo.put(OutputFile.service, codeGeneratorConfig.getServiceOutputDir());
        pathInfo.put(OutputFile.serviceImpl,codeGeneratorConfig.getServiceImplOutputDir());
        pathInfo.put(OutputFile.controller, codeGeneratorConfig.getControllerOutputDir());
        pathInfo.put(OutputFile.xml, codeGeneratorConfig.getXmlOutputDir());

        FastAutoGenerator.create(url, username, password)
                .globalConfig(builder -> {
                    builder.author(author) // 设置作者
                            .enableSwagger() // 开启 swagger 模式
                            .fileOverride() // 覆盖已生成文件
                            .outputDir(codeGeneratorConfig.getEntityOutputDir())
                            ; // 指定输出目录
                })
                .packageConfig(builder -> {
                    builder.parent(basePackage) // 设置父包名
                            .entity("entity") // 设置实体包名
                            .service("service") // 设置service包名
                            .serviceImpl("service.impl")
                            .mapper("mapper")
                            .controller("controller")
                           .pathInfo(pathInfo);
                            //.pathInfo(Collections.singletonMap(OutputFile.xml, outputDir + "/mapper")); // 设置mapperXml生成路径
                })
                .strategyConfig(builder -> {
                    builder.addInclude(tableNames) // 设置需要生成的表名
                            .addTablePrefix(tablePrefix) // 设置过滤表前缀
                            .serviceBuilder()
                            .formatServiceFileName("%sService")// 设置service类名格式
                            .formatServiceImplFileName("%sServiceImpl")
                            .entityBuilder()
                            .enableLombok()
                            .enableTableFieldAnnotation()
                            .controllerBuilder()
                            .formatFileName("%sController")
                            .enableRestStyle()
                            .mapperBuilder()
                            .formatMapperFileName("%sMapper")
                            .formatXmlFileName("%sMapper");
                })
                .templateEngine(new VelocityTemplateEngine())
                .templateConfig(builder -> {
                    builder.entity("templates/entity.java.vm")
                            .service("templates/service.java.vm")
                            .serviceImpl("templates/serviceImpl.java.vm")
                            .controller("templates/controller.java.vm")
                            ;


                })
                .injectionConfig(builder -> {
                    //builder.customMap(Collections.singletonMap("queryPackage", basePackage + ".query"));
                    // 自定义输出Query类
                    builder.customFile(builder1 -> {
                        builder1.fileName("Query.java")
                                .templatePath("/templates/query.java.vm")
                                .packageName("query"); // 因为父包是basePackage，所以这里只需要写"query"
                    });})
                // 使用Velocity引擎模板
                // 在 CodeGenerator 中添加类型映射
                .dataSourceConfig(builder -> {
                    builder.typeConvertHandler((globalConfig, typeRegistry, metaInfo) -> {
                        int typeCode = metaInfo.getJdbcType().TYPE_CODE;
                        if (typeCode == Types.SMALLINT) {
                            return DbColumnType.INTEGER;
                        }
                        return typeRegistry.getColumnType(metaInfo);
                    });
                })
                .execute();
    }
}